#include <iostream>
#include <memory>

#if 0
    class Girl;
    class Boy
    {
    public:
        Boy()
        {
            std::cout << "boy构造!\n";
        }
        ~Boy()
        {
            std::cout << "boy析构!\n";
        }
        void SetGirl(std::shared_ptr<Girl> &g)
        {
            girlfriend = g;
        }

    private:
        // 指向一个shared_ptr的空间，但是不会引起引用计数器+1
        std::shared_ptr<Girl> girlfriend;
    };

    class Girl
    {
    public:
        Girl()
        {
            std::cout << "girl构造!\n";
        }
        ~Girl()
        {
            std::cout << "girl析构!\n";
        }
        void SetBoy(std::shared_ptr<Boy> &b)
        {
            boyfriend = b;
        }

    private:
        // 指向一个shared_ptr的空间，但是不会引起引用计数器+1
        std::shared_ptr<Boy> boyfriend;
    };


    int main()
    {
        std::shared_ptr<Boy> b = std::make_shared<Boy>();
        std::shared_ptr<Girl> g = std::make_shared<Girl>();
        
        // Boy里的girl指针指向Girl
        b->SetGirl(g); 
        // Girl里的boy指针指向Boy
        g->SetBoy(b); 

        // 现在在main函数里有一个b指针指向Boy这块内存
        // 当b释放的时候，理应要释放这块空间，但释放不了
        // 因为Girl里面的那个智能指针还指向Boy，就导致这个Boy对象没有释放
        // 同理对于Girl也一样
        // 循环引用问题：互相拿着对方的智能指针，最后谁都没有释放，导致内存泄漏
        // 不一定是两个类，可能是多个类
        // 对于shared_ptr来说，这个问题不好解决
        // 为了解决这个问题，给它打了个补丁—— weak_ptr
        return 0;
    }
#endif

#if 1
    // weak_ptr：弱指针
    // 指向一个shared_ptr的空间，但是不会引起引用计数器+1
    // 引用计数器不+1到时候就能释放掉了
    class Girl;
    class Boy
    {
    public:
        Boy()
        {
            std::cout << "boy构造!\n";
        }
        ~Boy()
        {
            std::cout << "boy析构!\n";
        }
        void SetGirl(std::shared_ptr<Girl> &g)
        {
            girlfriend = g;
        }

    private:
        std::weak_ptr<Girl> girlfriend;
    };

    class Girl
    {
    public:
        Girl()
        {
            std::cout << "girl构造!\n";
        }
        ~Girl()
        {
            std::cout << "girl析构!\n";
        }
        void SetBoy(std::shared_ptr<Boy> &b)
        {
            boyfriend = b;
        }

    private:
        std::weak_ptr<Boy> boyfriend;
    };


    int main()
    {
        std::shared_ptr<Boy> b = std::make_shared<Boy>();
        std::shared_ptr<Girl> g = std::make_shared<Girl>();

        b->SetGirl(g);
        g->SetBoy(b);

        // 原本是shared_ptr自己的问题，但是为了解决这个问题，又引入了一个全新的指针
        // 这个补丁打的不好，引起了新的学习成本
        // 所以这个指针很少去用，一般都是靠标准化的代码设计去解决这个问题
        // shared_ptr尽量不要放在一个类中充当它的对象
        // 放在一个类中就意味着它会和别的类的对象去共享同一块空间
        // 那就得有多个人去管理同一块空间
        // 那从类的对象角度就没有所谓的封装和独立性存在
        return 0;
    }
#endif